<?php
namespace Modules\Activity\Entities;

use Modules\Core\Entities\BaseEntity as Model;
use Modules\Order\Traits\Skuable;
use Modules\Asset\Entities\Package;
use Modules\Activity\Entities\ActivityOrder;

use \Modules\Activity\Entities\TicketRecord;
use \Modules\Agent\Entities\InviteRecord;

use \Modules\Activity\Entities\JoinStat;

use \Modules\Activity\Entities\Ticket;

use ThrowException;
use Asset;

class BaseActivityModel extends Model
{
    use Skuable;
    
    protected $guarded = ['sales', 'union_status', 'union_status_text', 'type_text', 'activity_type_text', 'activity_type'];

    protected $appends = ['union_status', 'union_status_text', 'activity_type_text', 'activity_type'];

    // 订单所属package
    public function package() 
    {
        return $this->hasOne('\Modules\Asset\Entities\Package', 'pay_order_id');
    }

    public function scopeAvailable($query)
    {
        return $query->status('on_stock')->status('working')->where('stock', '>', 0);
    }

    public function scopeStatus($query, $status) 
    {
        $now = now();
        
        if ($status === 'on_stock') {
            return $query->onStock();
        }
        elseif ($status === 'off_stock') {
            return $query->offStock();
        }
        elseif ($status === 'sell_out') {
            return $query->where('stock', '<=', 0);
        }
        elseif ($status === 'marked') {
            return $query->whereNotNull('marked_at');
        }
        elseif ($status === 'expired') {
            return $query->whereNotNull('end_at')->where('end_at', '<', $now);
        }
        elseif ($status === 'pending') {
            return $query->where('start_at', '>', $now);
        }
        elseif ($status === 'working') {
            return $query->where('start_at', '<', $now)->where(function ($q) use ($now) {
                return $q->whereNull('end_at')->orWhere('end_at', '>', $now);
            });
        }
        elseif ($status === 'unexpired') {
            return $query->whereNull('end_at')->orWhere('end_at', '>', $now);
        }
    }

    // 统一状态 英文
    public function getUnionStatusAttribute()
    {
        $status = 'unknow';

        $nowStr = date('Y-m-d H:i:s');

        if ($this->end_at && $this->end_at < $nowStr)
            $status = 'expired';
        elseif ($this->start_at > $nowStr)
            $status = 'pending';
        else {
            $status = 'working';
        }

        return $status;
    }

    // 统一状态 中文
    public function getUnionStatusTextAttribute()
    {
        $map = [
            'pending' => '未开始',
            'working' => '进行中',
            'expired' => '已结束',
        ];

        return @v($map[$this->union_status], '未知状态');
    }

    public function getActivityTypeAttribute()
    {
        return $this->activityType;
    }

    public function getActivityTypeTextAttribute()
    {
        return $this->activityTypeText;
    }

    static public function beforeGetList($options)
    {
        if (@$options['status']) {
            $options['scopes']['status']  = $options['status'];
        }

        return $options;
    }

    // 是否需要参与码
    public function isNeedJoinCode()
    {
        return $this->join_codes && count($this->join_codes);
    }

    // 检查参与码是否正确
    public function checkJoinCode($code)
    {
        return in_array($code, $this->join_codes ?: []);
    }

    // 检查每个用户限制参与次数
    public function checkPerUserLimit($user, $total)
    {
        if (!$this->per_user_limit) {
            return true;
        }

        $completedTotal = ActivityOrder::paid()->where('node_type', $this->activity_type)->where('user_id', $user->id)->where('node_id', $this->id)->sum('sku_total');

        if ($completedTotal + $total > $this->per_user_limit) {
            $remainTime = $this->per_user_limit - $completedTotal;
            $remainTime = $remainTime < 0 ? 0 : $remainTime;

            ThrowException::Conflict('整个活动每人限制参与' . $this->per_user_limit . '次， 您当前仅剩余' . $remainTime . '次参与机会~');
        }
    }

    // 获取某用户在此活动的参数次数
    // $room 为特定房间
    public function getJoinTotal($user, $options = [])
    {
        $builder = ActivityOrder::paid()->where('node_type', $this->activity_type)->where('user_id', $user->id)->where('node_id', $this->id);

        // 限制特定的房间
        if ($options['room']) {
            $builder = $builder->where('room_id', $options['room']->id);
        }

        $completedTotal = $builder->sum('sku_total');

        return $completedTotal;
    }


    // 统一获取开奖结果
    public function pickLuckySkus($total, $user = NULL, $order = NULL, $optoins = [])
    {
        // 此处由各个活动类自行派生实现

        return false;
    }

    public function pickLuckySku($user = NULL, $order = NULL, $optoins = [])
    {
        $skuMaps = $this->pickLuckySkus(1, $user, $order, $optoins);

        if ($skuMaps  && count($skuMaps) > 0) {
            return $skuMaps[0]['skuable'];
        }

        return false;
    }

    // 回调
    public function packageCreatedListenerSync($order, $package)
    {
        // 具体派生类中实现
    }

    // 订单完成支付
    public function orderPaidListenerSync($order)
    {
        // \Log::error('base activity paid listenersync');
        // 按正常，是创建package;
        return $order->createPackage();
        // $this->createPackage($order);
    }

    // 锁定当前活动的 package创建器 
    public function lockPackageCreator($order) 
    {
        // 默认为不需要上锁，部分活动需要上锁需要在派生活动中自行实现
        // return false;
        return true;
    }

    // 释放当前活动的 package创建器 
    public function releasePackageCreator($order) 
    {
        // 释放活动创建器
        return true;
    }

    // 扣除用户的次数
    public function ticketOut($user, $total, $options = [])
    {
        $description = @$options['description'] ?: '使用扣除';
        Ticket::out($user, $this, $total, $description) ?: ThrowException::Conflict('剩余次数不足~', 14002);
    }

    // 计算某用户在此活动已邀请人数
    public function calcInviteTotal($user)
    {
        if (!$user) {
            return 0;
        }

        return InviteRecord::where([
                    'status' => 1,
                    'direct_inviter_id' => $user->id,
                    'invite_node_uuid' => $this->uuid
                ])->count();
    }

    // 计算某用户在此活动已获得票数
    public function calcInviteReward($user)
    {
        if (!$user) {
            return 0;
        }

        return intVal(TicketRecord::belongInviteReward()
                ->where('node_uuid', $this->uuid)
                ->where('user_id', $user->id)
                ->sum('total'));
    }

    // 计算某用户的邀请信息
    public function calcInviteInfo($user)
    {
        $maxReward = @$this->invite_rule['max_reward'] ?: 0;

        $rewardTotal = $this->calcInviteReward($user);

        $avaliableReward = $maxReward <= $rewardTotal ? 0 : $maxReward - $rewardTotal;

        return [
            'invite_total' => $this->calcInviteTotal($user),
            'invite_reward' => $rewardTotal,
            'available_reward' => $avaliableReward
        ];
    }

    // 增加参与记录统计
    public function updateJoinStat($user, $info)
    {
        $stat = JoinStat::where('node_uuid', $this->uuid)->where('user_id', $user->id)->first();

        // 没有记录，先创建
        if (!$stat) {
            $stat = JoinStat::create([
                'user_id' => $user->id,
                'node_id' => $this->id,
                'node_uuid' => $this->uuid,
                'node_type' => $this->activityType,
            ]);

            // 创建新的参与记录，参与人数+1
            $this->update([
                'join_user_total' => $this->join_user_total + 1
            ]);
        }

        // 更新次数
        if (@$info['total']) {
            $stat->total += $info['total'];
        }

        // 更新次数
        if (@$info['paid_balance']) {
            $stat->paid_balance += $info['paid_balance'];
        }

        // 更新次数
        if (@$info['paid_score']) {
            $stat->paid_score += $info['paid_score'];
        }

        // 更新次数
        if (@$info['paid_money']) {
            $stat->paid_money += $info['paid_money'];
        }

        $stat->save();
    }


    // 发放邀请活动的奖励
    public function sendInviteReward($user, $invited, $inviteIndex)
    {
        // 未开启邀请奖励设置
        if (!$this->is_invite_enabled) {
            return false;
        }

        $inviteRule = $this->invite_rule ?: [];

        // 奖励被邀请者
        if (@$inviteRule['is_invited_reward_enabled']) {
            $reward = @$inviteRule['invited_reward'];

            Asset::sendSingleReward($reward, $invited, [
                'description' => '活动注册奖励',
                'node' => $this
            ]);
        }


        $rewardList = @$inviteRule['reward_list'];

        // 目标奖励规则
        $targetReward = collect($rewardList)->where('total', $inviteIndex)->first();

        // 有指定奖励
        if ($targetReward) {
            return Asset::sendSingleReward($targetReward['reward'], $user, [
                'description' => '活动邀请-第' . $inviteIndex . '人奖励',
                'node' => $this
            ]);
        }

        return false;
    }

    public function sendInviteRewardNew($user, $invited, $inviteIndex)
    {
        // 未开启邀请奖励设置
        if (!$this->is_share_enabled) {
            return false;
        }
        $inviteRule = $this->share_rule ?: [];

        // 奖励被邀请者
        if (@$inviteRule['is_invited_reward_enabled']) {
            $reward = @$inviteRule['invited_reward'];

            Asset::sendSingleReward($reward, $invited, [
                'description' => '活动分享奖励',
                'node' => $this
            ]);
        }


        $rewardList = @$inviteRule['reward_list'];

        // 目标奖励规则
        $targetReward = collect($rewardList)->where('total', $inviteIndex)->first();

        // 有指定奖励
        if ($targetReward) {
            return Asset::sendSingleReward($targetReward['reward'], $user, [
                'description' => '活动分享-第' . $inviteIndex . '人奖励',
                'node' => $this
            ]);
        }

        return false;
    }

}
